#include <REGX52.H>
#include "Timer0.h"
#include "Int0.h"

unsigned int IR_Time;	//计时
unsigned char IR_State;	//状态（状态机）

unsigned char IR_Data[4];	//（数据缓存变量）十六位以下可以或等于运算，大于16位就会出错，所以改成数组，四个字节，32位
unsigned char IR_pData;		//（记录存储到第几位了）指向当前的位置，每进来一次本变量++

unsigned char IR_DataFlag;	//数据结束，置1，用来判断
unsigned char IR_RepeatFlag;//重发标志位
unsigned char IR_Address;	//缓存变量整合之后，存放在这里
unsigned char IR_Command;	//命令码

/**
  * @brief  红外遥控初始化
  * @param  无
  * @retval 无
  */
void IR_Init(void)
{
	Timer0_Init();
	Int0_Init();
}

/**
  * @brief  红外遥控获取收到数据帧标志位
  * @param  无
  * @retval 是否收到数据帧，1为收到，0为未收到
  */
unsigned char IR_GetDataFlag(void)
{
	if(IR_DataFlag)//如果是1
	{
		IR_DataFlag = 0;//给他置0
		return 1;//返回1
	}
	return 0;//if不成立，才返回0
}

/**
  * @brief  红外遥控获取收到连发帧标志位
  * @param  无
  * @retval 是否收到连发帧，1为收到，0为未收到
  */
unsigned char IR_GetRepeatFlag(void)
{
	if(IR_RepeatFlag)//如果是1
	{
		IR_RepeatFlag = 0;//给他置0
		return 1;//返回1
	}
	return 0;//if不成立，才返回0
}

/**
  * @brief  红外遥控获取收到的地址数据
  * @param  无
  * @retval 收到的地址数据
  */
unsigned char IR_GetAddress(void)
{
	return IR_Address;
}

/**
  * @brief  红外遥控获取收到的命令数据
  * @param  无
  * @retval 收到的命令数据
  */
unsigned char IR_GetCommand(void)
{
	return IR_Command;
}




//外部中断0中断函数，下降沿触发执行
void Int0_Routine(void) interrupt 0
{
	if(IR_State==0)				//状态0，空闲状态
	{
		Timer0_SetCounter(0);	//定时计数器清0
		Timer0_Run(1);			//定时器启动
		IR_State=1;				//置状态为1
	}
	else if(IR_State==1)		//状态1，等待Start信号或Repeat信号
	{
		IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间
		Timer0_SetCounter(0);	//定时计数器清0
		//如果计时为13.5ms，则接收到了Start信号（判定值在12MHz晶振下为13500，在11.0592MHz晶振下为12442）
		if(IR_Time>12442-500 && IR_Time<12442+500)
		{
			IR_State=2;			//置状态为2
		}
		//如果计时为11.25ms，则接收到了Repeat信号（判定值在12MHz晶振下为11250，在11.0592MHz晶振下为10368）
		else if(IR_Time>10368-500 && IR_Time<10368+500)
		{
			IR_RepeatFlag=1;	//置收到连发帧标志位为1
			Timer0_Run(0);		//定时器停止
			IR_State=0;			//置状态为0
		}
		else					//接收出错
		{
			IR_State=1;			//置状态为1
		}
	}
	else if(IR_State==2)		//状态2，接收数据
	{
		IR_Time=Timer0_GetCounter();	//获取上一次中断到此次中断的时间
		Timer0_SetCounter(0);	//定时计数器清0
		//如果计时为1120us，则接收到了数据0（判定值在12MHz晶振下为1120，在11.0592MHz晶振下为1032）
		if(IR_Time>1032-500 && IR_Time<1032+500)
		{
			IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));	//数据对应位清0
			IR_pData++;			//数据位置指针自增
		}
		//如果计时为2250us，则接收到了数据1（判定值在12MHz晶振下为2250，在11.0592MHz晶振下为2074）
		else if(IR_Time>2074-500 && IR_Time<2074+500)
		{
			IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));	//数据对应位置1
			IR_pData++;			//数据位置指针自增
		}
		else					//接收出错
		{
			IR_pData=0;			//数据位置指针清0
			IR_State=1;			//置状态为1
		}
		if(IR_pData>=32)		//如果接收到了32位数据
		{
			IR_pData=0;			//数据位置指针清0
			if((IR_Data[0]==~IR_Data[1]) && (IR_Data[2]==~IR_Data[3]))	//数据验证
			{
				IR_Address=IR_Data[0];	//转存数据
				IR_Command=IR_Data[2];
				IR_DataFlag=1;	//置收到连发帧标志位为1
			}
			Timer0_Run(0);		//定时器停止
			IR_State=0;			//置状态为0
		}
	}
}




///* 跟着视频敲得，有问题，找不到
//void Int0_Routine(void) interrupt 0		//外部中断0，中断号是0
//{	//下降沿才触发本中断
//	if(IR_State == 0)	//0状态
//	{		
//		Timer0_SetCounter(0);	//清零
//		Timer0_Run(1);		//开始计时
//		IR_State = 1;
//	}	//第一次进中断是状态0，下面的就不会运行了
//	else if(IR_State == 1)	//第二次进中断（第二个下降沿）时候为1状态
//	{
//		IR_Time = Timer0_GetCounter();	//读取时间
//		Timer0_SetCounter(0);	//清零，方便下次计时
//		if(IR_Time > 12442-500  &&  IR_Time < 12442+500)	//1us计数器加1
//		{	//这个时间段是start信号(9ms+4.5ms)
////			P2=0xfe;不亮，应该没进来本段
//			IR_State = 2;	//置状态2
//		}	
//		else if(IR_Time > 10368-500  &&  IR_Time < 10368+500)
//		{	//重发信号(9ms+2.25ms)
//					
//			IR_RepeatFlag = 1;	//收到重发信号
//			Timer0_Run(0);		//暂停计时
//			IR_State = 0;		//变回0状态
//		}
//		else	//错误的话，变成1状态，继续搜开始信号
//		{
//			IR_State = 1;		//改回1状态
//		}
//	}
//	else if(IR_State == 2)	//2状态开始解码
//	{
//		IR_Time = Timer0_GetCounter();	//读取时间(上一次中断到这一次中断的时间)
//		Timer0_SetCounter(0);	//立即清零，方便下次计时
//		if(IR_Time > 1032-500  &&  IR_Time < 1032+500)	//1us计数器加1
//		{	//这个时间段是逻辑0信号(560us+560us)，对应位清零
//			//写入数据
//			IR_Data[IR_pData/8] &= ~(0x01<<(IR_pData%8));
//			IR_pData++;
//			/*
//			这里是 与等于  先左移，再取反
//			与运算  同为1 才为1
//			这里是 0000 0001 取反变成1111 1110
//			左移一次变成0000 0010 取反变成1111 1101，现在再进行与运算就不影响后边的数据了
//			但定义八位的数据，0-31要拆分成4个字节
//			0-31对8取整是当前第几个（0123）字节，取余是第几位（01234567）
//			*/
//		}
//		else if(IR_Time > 2074-500  &&  IR_Time < 2074+500)	//1us计数器加1
//		{	//这个时间段是逻辑1信号(560us+1690us)，对应位置1
//			//写入数据
//			IR_Data[IR_pData/8] |= (0x01<<(IR_pData%8));
//			IR_pData++;
//			/*
//			这里是 或等于  
//			或运算  有1就为1
//			
//			左移后边补0，现在再进行或运算不会影响后边的数据
//			同样定义八位的数据，0-31要拆分成4个字节
//			0-31对8取整是当前第几个（0123）字节，取余是第几位（01234567）
//			*/
//		}
//		else 
//		{//如果数据接受有错误，就重新搜起始信号，得先把IR_pData置零
//			IR_pData = 0;
//			IR_State = 1;
//		}
//		if(IR_pData>=32)//收完数据了
//		{
//			IR_pData=0;
//			//Data的格式：地址码+地址反码+命令码+命令反码
//			if((IR_Data[0] == ~IR_Data[1]) && (IR_Data[2] == ~IR_Data[3]))
//			IR_Address = IR_Data[0];
//			IR_Command = IR_Data[2];
//			IR_DataFlag = 1;
//		}
//		Timer0_Run(0);	//暂停定时器	
//		IR_State = 0;	//回到空闲状态
//		
//	}
//		
//	
//	
//}



/*
IR解码，内含两个模块，Int0  Timer0 
定时器0用来定时计数，改造定时器0，读取时间差
运用状态机 0、1、2状态

0状态表示空闲状态，收到下降沿，就打开定时器，开始计时，状态置1
1状态是 寻找start或repeat 头部的信号
如果是 0状态的下降沿  到  1状态头部的下降沿，就读取0状态到1状态的时间
判断这个时间，如果是起始信号，就转到2状态
如果是重发信号，就把重发标志位置1，切回0状态
2状态就开始解码32bit的数据，连续32次
每进行一次2状态，就会计算1 0的时间差，把这个数据填充到Data这个变量缓存区
再定义一个变量，用来指示现在存储到第几位了
存完32次，就认为数据收到了
收到数据，然后就验证数据，（第一个字节取反是否和第二个字节相等）
如果相等，置一个 收到数据的标志位Data_Flag，然后把状态切回到0状态


*/



